using Abp.Application.Services.Dto;
using Abp.AutoMapper;
using Abp.Domain.Entities.Auditing;
using Abp.Domain.Repositories;
using Abp.Linq.Extensions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Yozeev.BusinessLogic;
using Yozeev.BusinessLogic.Dtos;
using Yozeev.BusinessLogic.Stats.Dtos;
using Yozeev.BusinessLogic.TicketLogic.Dtos;
using Yozeev.Common;
using Yozeev.Controllers.Stats.Detail;
using Yozeev.Controllers.Stats.Filters;
using Yozeev.Dtos;
using Yozeev.SystemConfig;
using Yozeev.UserManagerment.Users;

namespace Yozeev.Controllers.Stats
{
    /// <summary>
    /// 销售员售票统计
    /// </summary>
    [Route("api/Stats/[Controller]/[Action]")]
    public class SellerDailyController : YozeevControllerBase
    {
        private readonly IRepository<Activity, Guid> _activityRep;

        private readonly IRepository<User, long> _userRep;

        private readonly IRepository<PayMethod, Guid> _payMethodRep;

        private readonly IRepository<TicketDetail, Guid> _ticketDetailRep;

        private readonly IRepository<TicketPrice, Guid> _ticketPriceRep;

        private readonly IRepository<ActivityDetail, Guid> _activityDetail;

        private readonly IRepository<Schedule, Guid> _scheduleRep;

        private readonly IGetDetailable _statDetail;

        private readonly AbstractFilter _salerFilter;

        private readonly AbstractFilter _boatFilter;

        private readonly AbstractFilter _ticketTypeFilter;

        private readonly AbstractFilter _routeFilter;

        private readonly IQueryHelper _queryHelper;

        public SellerDailyController(
            IRepository<Activity, Guid> activityRep,
            IRepository<User, long> userRep,
            IRepository<PayMethod, Guid> payMethodRep,
            IRepository<TicketDetail, Guid> ticketDetailRep,
            IRepository<Schedule, Guid> scheduleRep,
            IRepository<TicketPrice, Guid> ticketPriceRep,
            IRepository<ActivityDetail, Guid> activityDetail,
            StatDetail statDetail,
            SalerFilter salerFilter,
            BoatFilter boatFilter,
            TicketTypeFilter ticketTypeFilter,
            RouteFilter routeFilter,
            IQueryHelper queryHelper)
        {
            _statDetail = statDetail;
            _activityRep = activityRep;
            _userRep = userRep;
            _payMethodRep = payMethodRep;
            _ticketDetailRep = ticketDetailRep;
            _salerFilter = salerFilter;
            _boatFilter = boatFilter;
            _ticketTypeFilter = ticketTypeFilter;
            _routeFilter = routeFilter;
            _scheduleRep = scheduleRep;
            _ticketPriceRep = ticketPriceRep;
            _activityDetail = activityDetail;
            _queryHelper = queryHelper;
        }

        /// <summary>
        /// 销售员日结统计
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<StatsPagedResultDto<SellerDailyResultDto>> GetPaged(SellerTicketInput input, string boatId, string ticketId)
        {
            var users = _userRep.GetAll();
            var userIds = users.Select(u => u.Id).ToList();
            var paymethods = _payMethodRep.GetAll();
            var activities = _activityRep.GetAll()
                .Where(a => userIds.Contains((long)a.CreatorUserId))
                .Where(_queryHelper.WhereExp<Activity>(input.queryData));
            DateTime startDateTime = DateTime.Today; //Today at 00:00:00
            DateTime endDateTime = DateTime.Today.AddDays(1).AddTicks(-1); //Today at 23:59:59
            if (input.queryData == null || 
                input.queryData.Where(q => q.Field == "CreationTime").ToList().Count < 1)
            {
                activities = activities.Where(ac => ac.CreationTime >= startDateTime && ac.CreationTime <= endDateTime);
            }

            if (!string.IsNullOrEmpty(boatId))
            {
                var scheduleIds = _scheduleRep.GetAll().Where(s => s.BoatId.ToString()
                .Equals(boatId)).Select(s => s.Id).ToList();
                activities = activities.Where(a => scheduleIds.Contains(a.ScheduleId.Value));
            }

            if (!string.IsNullOrEmpty(ticketId))
            {
                var ticketPriceIds = _ticketPriceRep.GetAll()
                    .Where(t => t.TicketId.ToString().Equals(ticketId)).Select(t => t.Id).ToList();
                var activityIds = _activityDetail.GetAll()
                    .Where(a => ticketPriceIds.Contains(a.TicketPriceId))
                    .Select(a => a.ActivityId)
                    .ToList();
                activities = activities.Where(a => activityIds.Contains(a.Id));
            }

            var tmp1 = from activity in activities
                       where activity.PayStatus == PayStatusEnum.PayStatusPayment || activity.PayStatus == PayStatusEnum.PayStatusRefund
                       join paymethod in paymethods
                       on activity.PayMethod equals paymethod
                       group activity by new { activity.CreatorUser, activity.PayMethod } into a
                       select new
                       {
                           CreatorUserId = a.Key.CreatorUser.Id,
                           //售票金额
                           CashSaleAmount = a.Sum(ac => ac.PayMethod.PayCode == "Cash" ? (ac.ActivityType == ActivityTypeEnum.ActivityTypePayment ? ac.TotalAmount : 0) : 0),
                           WeiChatSaleAmount = a.Sum(ac => ac.PayMethod.PayCode == "WeiChat" ? (ac.ActivityType == ActivityTypeEnum.ActivityTypePayment ? ac.TotalAmount : 0) : 0),
                           CardSaleAmount = a.Sum(ac => ac.PayMethod.PayCode == "Card" ? (ac.ActivityType == ActivityTypeEnum.ActivityTypePayment ? ac.TotalAmount : 0) : 0),
                           ZhiFuBaoSaleAmount = a.Sum(ac => ac.PayMethod.PayCode == "ZhiFuBao" ? (ac.ActivityType == ActivityTypeEnum.ActivityTypePayment ? ac.TotalAmount : 0) : 0),
                           //退票金额
                           CashRefundAmount = a.Sum(ac => ac.PayMethod.PayCode == "Cash" ? (ac.ActivityType == ActivityTypeEnum.ActivityTypeRefund ? ac.TotalAmount : 0) : 0),
                           WeiChatRefundAmount = a.Sum(ac => ac.PayMethod.PayCode == "WeiChat" ? (ac.ActivityType == ActivityTypeEnum.ActivityTypeRefund ? ac.TotalAmount : 0) : 0),
                           CardRefundAmount = a.Sum(ac => ac.PayMethod.PayCode == "Card" ? (ac.ActivityType == ActivityTypeEnum.ActivityTypeRefund ? ac.TotalAmount : 0) : 0),
                           ZhiFuBaoRefundAmount = a.Sum(ac => ac.PayMethod.PayCode == "ZhiFuBao" ? (ac.ActivityType == ActivityTypeEnum.ActivityTypeRefund ? ac.TotalAmount : 0) : 0),
                           //售票数量
                           SaleCount = a.Sum(ac => ac.ActivityType == ActivityTypeEnum.ActivityTypePayment ? ac.TotalQuantity : 0),
                           //退票数量
                           RefundCount = a.Sum(ac => ac.ActivityType == ActivityTypeEnum.ActivityTypeRefund ? ac.TotalQuantity : 0)
                       };
            //计算小计
            var tmp2 = from tmp in tmp1
                       group tmp by tmp into g
                       select new SellerDailyResultDto
                       {
                           Saler = (from user in users where user.Id == g.Key.CreatorUserId select user).FirstOrDefault(),
                           CashSaleAmount = g.Key.CashSaleAmount,
                           WeiChatSaleAmount = g.Key.WeiChatSaleAmount,
                           CardSaleAmount = g.Key.CardSaleAmount,
                           ZhiFuBaoSaleAmount = g.Key.ZhiFuBaoSaleAmount,
                           //退票金额
                           CashRefundAmount = g.Key.CashRefundAmount,
                           WeiChatRefundAmount = g.Key.WeiChatRefundAmount,
                           CardRefundAmount = g.Key.CardRefundAmount,
                           ZhiFuBaoRefundAmount = g.Key.ZhiFuBaoRefundAmount,
                           //售票数量
                           SaleCount = g.Key.SaleCount,
                           //退票数量
                           RefundCount = g.Key.RefundCount,
                           //小结
                           TotalCount = g.Key.SaleCount - g.Key.RefundCount,
                           TotalSaleAmount = g.Key.CashSaleAmount + g.Key.WeiChatSaleAmount + g.Key.CardSaleAmount + g.Key.ZhiFuBaoSaleAmount,
                           TotalRefundAmount = g.Key.CashRefundAmount + g.Key.WeiChatRefundAmount + g.Key.CardRefundAmount + g.Key.ZhiFuBaoRefundAmount,
                           TotalAmount = g.Key.CashSaleAmount + g.Key.WeiChatSaleAmount + g.Key.CardSaleAmount + g.Key.ZhiFuBaoSaleAmount - (g.Key.CashRefundAmount + g.Key.WeiChatRefundAmount + g.Key.CardRefundAmount + g.Key.ZhiFuBaoRefundAmount)
                       };
            var count = await tmp2.CountAsync();
            var result = await tmp2.ToListAsync();

            Dictionary<string, IEnumerable<object>> filters = new Dictionary<string, IEnumerable<object>>();
            _salerFilter.Decorate(filters);
            _boatFilter.Decorate(filters);
            _ticketTypeFilter.Decorate(filters);
            _routeFilter.Decorate(filters);

            return new StatsPagedResultDto<SellerDailyResultDto>(count, result.AsQueryable().PageBy(input).ToList(), filters);
        }

        /// <summary>
        /// 销售员日结统计——详细
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<List<AccountDetailDto>> Detail(string userId)
        {
            var activities = _activityRep.GetAll()
                .Where(activity => activity.CreatorUserId.ToString() == userId);
            return _statDetail.GetDetailByActivities(activities);
        }
    }
}
